package stkr;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.util.Calendar;
import java.util.Currency;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Stock {

	private String stockName;
	private String exchangeName;
	private Currency currencyCode;
	private BigDecimal lastPrice;
	private String companyName;
	private transient BigDecimal currentPrice;
	private transient BigDecimal openPrice;
	private transient Boolean hasChanged;
	private transient Date lastUpdate;

	public Stock(String stockName, String exchangeName) {
		Logger.getLogger(StkrConstants.loggerFile).log(
				Level.ALL,
				"New Stock " + exchangeName + ":" + stockName
						+ " is getting created");
		setStockName(stockName);
		setExchangeName(exchangeName);
	}

	public Stock(String stockName, String exchangeName, Currency currencyCode,
			BigDecimal lastPrice) {
		Logger.getLogger(StkrConstants.loggerFile).log(
				Level.ALL,
				"New Stock " + exchangeName + ":" + stockName
						+ " is getting created with last Price " + currencyCode
						+ " " + lastPrice);
		setStockName(stockName);
		setExchangeName(exchangeName);
		setLastPrice(lastPrice);
		setCurrencyCode(currencyCode);
	}

	public void updateStock() throws IOException {

		Logger localLog = Logger.getLogger(StkrConstants.loggerFile);

		localLog.log(Level.ALL, exchangeName + ":" + stockName + ": Stock "
				+ this.getExchangeName() + ":" + this.getStockName()
				+ "is getting Updated");

		URL url = new URL("http://www.google.com/finance?q=" + exchangeName
				+ ":" + stockName);
		localLog.log(Level.ALL, exchangeName + ":" + stockName
				+ ": URL formed is " + url);
		URLConnection urlConn = url.openConnection();
		InputStreamReader inStream = new InputStreamReader(
				urlConn.getInputStream());
		BufferedReader buff = new BufferedReader(inStream);
		while (true) {
			String nextLine = buff.readLine();
			if (nextLine != null) {

				if (getCompanyName() == null
						&& nextLine.startsWith("</script><title>")) {
					setCompanyName(nextLine.substring(16).split(":")[0]);
					localLog.log(Level.ALL, exchangeName + ":" + stockName
							+ ": Company name is not set. Setting it to "
							+ this.getCompanyName());
				} else {

				}
				if (getCurrencyCode() == null
						&& nextLine.startsWith("<div>Currency in")) {
					setCurrencyCode(Currency.getInstance(nextLine.substring(17,
							20)));
					localLog.log(Level.ALL, exchangeName + ":" + stockName
							+ ": Currency Code is not set. Setting it to "
							+ this.getCurrencyCode());
				}
				if (nextLine.startsWith("          data-snapfield=\"open\">")) {

					localLog.log(Level.ALL, exchangeName + ":" + stockName
							+ ": Open Price is " + this.getOpenPrice());
					
					nextLine = buff.readLine();
					nextLine = buff.readLine();
					try{
					setOpenPrice(new BigDecimal(nextLine.substring(16)));
					}catch(NumberFormatException e){
						setOpenPrice(null);
					}
					localLog.log(Level.ALL, exchangeName + ":" + stockName
							+ ": Updating Open Price to " + this.getOpenPrice());
				}

				if (nextLine.equalsIgnoreCase("<span class=\"pr\">")) {
					localLog.log(Level.ALL, exchangeName + ":" + stockName
							+ ": Current Price is " + this.getCurrentPrice());
					nextLine = buff.readLine();
					setLastPrice(getCurrentPrice());
					setCurrentPrice(new BigDecimal(
							nextLine.split("<")[1].split(">")[1]));
					localLog.log(
							Level.ALL,
							exchangeName + ":" + stockName
									+ ": Updating Current Price to "
									+ this.getCurrentPrice());
				}

			} else {
				break;
			}
		}

		inStream.close();
		buff.close();

		if (currentPrice.equals(lastPrice)) {
			localLog.log(Level.ALL, exchangeName + ":" + stockName
					+ ": Current Price has not changed ");
			setHasChanged(false);
		} else {
			setHasChanged(true);
			localLog.log(Level.ALL, exchangeName + ":" + stockName
					+ ": Current Price has changed ");
		}
		setLastUpdate(Calendar.getInstance().getTime());
	}

	private void setCompanyName(String companyName) {
		this.companyName = companyName;
	}

	public String getCompanyName() {
		return companyName;
	}

	private void setStockName(String stockName) {
		this.stockName = stockName;
	}

	private void setExchangeName(String exchangeName) {
		this.exchangeName = exchangeName;
	}

	private void setCurrencyCode(Currency currencyCode) {
		this.currencyCode = currencyCode;
	}

	private void setLastPrice(BigDecimal lastPrice) {
		this.lastPrice = lastPrice;
	}

	private void setCurrentPrice(BigDecimal currentPrice) {
		this.currentPrice = currentPrice;
	}

	private void setOpenPrice(BigDecimal openPrice) {
		this.openPrice = openPrice;
	}

	private void setHasChanged(Boolean hasChanged) {
		this.hasChanged = hasChanged;
	}

	private void setLastUpdate(Date lastUpdate) {
		this.lastUpdate = lastUpdate;
	}

	public String getStockName() {
		return stockName;
	}

	public String getExchangeName() {
		return exchangeName;
	}

	public Currency getCurrencyCode() {
		return currencyCode;
	}

	public BigDecimal getLastPrice() {
		return lastPrice;
	}

	public BigDecimal getCurrentPrice() {
		return currentPrice;
	}

	public BigDecimal getOpenPrice() {
		return openPrice;
	}

	public Boolean getHasChanged() {
		return hasChanged;
	}

	public Date getLastUpdate() {
		return lastUpdate;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((exchangeName == null) ? 0 : exchangeName.hashCode());
		result = prime * result
				+ ((stockName == null) ? 0 : stockName.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Stock other = (Stock) obj;
		if (exchangeName == null) {
			if (other.exchangeName != null)
				return false;
		} else if (!exchangeName.equals(other.exchangeName))
			return false;
		if (stockName == null) {
			if (other.stockName != null)
				return false;
		} else if (!stockName.equals(other.stockName))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Stock [stockName=" + stockName + ", exchangeName="
				+ exchangeName + ", currencyCode=" + currencyCode
				+ ", lastPrice=" + lastPrice + ", companyName=" + companyName
				+ ", currentPrice=" + currentPrice + ", openPrice=" + openPrice
				+ ", hasChanged=" + hasChanged + ", lastUpdate=" + lastUpdate
				+ "]";
	}

}
